package com.nt.train.controller;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.nt.train.dto.CustomNavigationDto;
import com.nt.train.vo.ResultVo;
import com.nt.train.vo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpHeaders;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

/**
 * https://www.jb51.net/article/242412.htm
 * https://blog.csdn.net/juligang320/article/details/124969650
 *  演示springboot请求方式
 *  SpringBoot中Controller用法及传参
 * @author hlf
 * @version 1.0
 * @date 2022/7/31 21:34
 * @Controller + @ResponseBody
 */
@RestController
@RequestMapping("/boot")
public class BootPostController {

    /*-------------------------post 参数处理 -----------------*/
    /*
     * 多种post请求访问方式  无参处理
     *  @RequestMapping(value = "/secondPost", method = RequestMethod.POST)
     *  如果限定Post请求方式， 用@PostMapping 代替 @RequestMapping
     * @GetMapping("/second")
     */
    //post请求传参：http://localhost:8080/boot/secondPost
    @RequestMapping(value = "/secondPost", method = RequestMethod.POST)
   // public ResultVo secondPost(){
    public ResultVo secondPost(HttpServletRequest request,HttpServletResponse response){
        User user = new User("李亚男", 40,"女");
        return ResultVo.ok(user);
    }

    /*
    * 第二种：以实体类接收
    * http://localhost:8080/boot/testEntity
    * {"userName": "zhangsan","id":"2"}
    * */
    @RequestMapping(value = "/testEntity",method=RequestMethod.POST)
    public ResultVo testEntity(@RequestBody User user) throws Exception{
        System.out.println("username:"+user.getUserName());
        return ResultVo.ok(user);
    }

    /*
     * 第三种：以Map接收
     * http://localhost:8080/boot/testMap
     * {"userName": "zhangsan","id":"2"}
     * */
    @RequestMapping(value = "/testMap",method=RequestMethod.POST)
    public ResultVo testMap(@RequestBody Map<String, String> map) throws Exception{
        System.out.println("userName:"+map.get("userName"));
        return ResultVo.ok(map);
    }

    /*
     * 第四种：以List接收
     * http://localhost:8080/boot/testList
     * [{"userName": "zhangsan","id":"2"},{"userName": "lisi","id":"1"}]
     * */
    @RequestMapping(value = "/testList",method=RequestMethod.POST)
    public ResultVo testList(@RequestBody List<User> list) throws Exception{
        for(User user:list){
            System.out.println("userName:"+user.getUserName());
        }
        return ResultVo.ok(list);
    }

    /*
     * 第五种：以JSON对象接收
     * http://localhost:8080/boot/testJson
     * {"userName": "zhangsan","id":"2","role":{"roleName":"admin"}}
     * */
    @RequestMapping(value = "/testJson",method=RequestMethod.POST)
    public ResultVo testJson(@RequestBody JSONObject json) throws Exception {
        System.out.println("userName:" + json.getString("userName"));
        System.out.println("roleName:" + json.getJSONObject("role").getString("roleName"));
        return ResultVo.ok(json);
    }

    /**
     * post请求传参：http://localhost:8080/boot/postForm
     *Post请求传参
     Post请求传参的方式，常用的有两种，一中是通过form表单进行传参（就是html中的form），
     还有一种是通过json的形式传参。目前来说用json的比较多。
     post请求需要通过postman来模拟了，注意form传参的位置，要在body的form-data里
     */
    @PostMapping("/postForm")
    public ResultVo postForm(String name, Integer age){
        User u = new User(name, age, null);
        return ResultVo.ok(u);
    }

    //如果参数过多，我们也是可以通过一个javaBean来进行接收
    @PostMapping("/postForm2")
    //post请求传参：http://localhost:8080/boot/postForm2
    public ResultVo postForm2(User user){
        return ResultVo.ok(user);
    }

    //如果参数过多，我们也是可以通过一个javaBean来进行接收
    @PostMapping("/postForm3")
    //post请求传参：http://localhost:8080/boot/postForm2
    public ResultVo postForm3(@RequestParam  Map user){
        return ResultVo.ok(user);
    }

    @PostMapping("/postTestJson")
    //post请求传参：http://localhost:8080/boot/postTestJson
    public ResultVo postTestJson(@RequestBody  JSONObject json){
   // public ResultVo postTestJson(@RequestParam  JSONObject json){
        return ResultVo.ok(json);
    }


    /**
     * Json 传参 注意坑点  无参构造方式
     通过json传递的参数，content-type一般为： application/json
     我们在接收参数的时候要通过一个新的注解 @RequestBody 来进行标识。
     * @param user
     * @return
     */
    @PostMapping("/postJson")
    public ResultVo postJson(@RequestBody User user){
        return ResultVo.ok(user);
    }

    /**
     * Json 传参 注意坑点  无参构造方式
     通过json传递的参数，content-type一般为： application/json
     我们在接收参数的时候要通过一个新的注解 @RequestBody 来进行标识。
     * @param user
     * @return
     */
    @PostMapping("/postJson/{id}")
    public ResultVo postJson(@PathVariable String id,@RequestBody User user){
        Map<String,Object>  resultMap = new HashMap<>();
        resultMap.put("id",id);
        resultMap.put("user",user);
        resultMap.put("success","success");
        return ResultVo.ok(resultMap);
    }

    /**
     * 关于@RequestParam注解
     还有一种方式，这种方式不是很常用，但有的时候，跟三方接口对接的时候，不排除他们使用这种方式。
     就是针对content-type是： application/x-www-form-urlcoded （Http协议中，如果不指定Content-Type，
     则默认传递的参数就是application/x-www-form-urlencoded类型）
     */
    @PostMapping("/postWWWForm")
   // public User postWWWForm(@RequestParam String name, @RequestParam Integer  age){
   // public User postWWWForm(String name,Integer  age){
//     public User postWWWForm(@RequestParam(value="id",required =false,defaultValue ="10086") Integer id,
//         @RequestParam String name, @RequestParam Integer  age){
    public ResultVo postWWWForm(@RequestParam(value="id",required =true) Integer id,
         @RequestParam String name, @RequestParam Integer  age){
        System.out.println("id="+id);
        User user= new User(name, age, null);
        return ResultVo.ok(user);
    }

    // @RequestBody接收请求体参数 json格式
    @PostMapping("/getBody")
    public ResultVo getBody(@RequestBody String id){
        return ResultVo.ok(id);
    }

    //@PostMapping("getHeader")
    @PostMapping("/getHeader")
    public ResultVo getHeader(@RequestHeader String id){
        return ResultVo.ok(id);
    }

    @PostMapping("/getHeader2")
    public ResultVo getHeader(@RequestHeader String id,@RequestBody User user){
        Map<String,Object>  resultMap = new HashMap<>();
        resultMap.put("id",id);
        resultMap.put("user",user);
        return ResultVo.ok(resultMap);
    }

    /** 针对请求头 处理     */
    @GetMapping("/init1")
    public ResultVo init1(@RequestHeader(value = "name", required = false, defaultValue = "ready") String name,
                      @RequestHeader(value = "age") int age,
                      // 默认为true,如果在前端可能不指定的话,需要手动改为非必须请求头,否则报错
                      @RequestHeader(value = "sex", required = false) String sex,
                      // 一个请求头中有多个值,使用List来接收
                      @RequestHeader(value = "addressList") List<String> addressList) {
        System.out.println(name);
        System.out.println(age);
        System.out.println(sex);
        System.out.println(addressList);
        Map<String,Object>  resultMap = new HashMap<>();
        resultMap.put("name",name);
        resultMap.put("age",age);
        resultMap.put("sex",sex);
        resultMap.put("addressList",addressList);
        return ResultVo.ok(resultMap);
    }


    @GetMapping("/init2")
    public ResultVo init2(@RequestHeader Map<String, String> headerMap) {
        // 使用Map接收所有的请求头
        System.out.println(headerMap);
        // js中使用header名为addressList,使用map接收后需要使用addresslist
        System.out.println(headerMap.get("addresslist"));  // address1,address2
        return ResultVo.ok(headerMap);
    }

    @GetMapping("/init3")
    public ResultVo init3(@RequestHeader MultiValueMap multiValueMap) {

        // 使用MultiValueMap来接收所有的请求头
        System.out.println(multiValueMap);
        return  ResultVo.ok(multiValueMap);
    }
    @GetMapping("/init4")
    public ResultVo init4(@RequestHeader HttpHeaders httpHeaders) {
        // 使用HttpHeaders接收所有的请求头
        Map<String,List<String>> result = new LinkedHashMap<>(httpHeaders);
        System.out.println(result);
        return ResultVo.ok(httpHeaders);
    }

    @RequestMapping(value = "/customNavigationSort", method = RequestMethod.POST)
    public ResultVo customNavigationSort(@RequestBody JSONArray jsonParam) {
        List<CustomNavigationDto> customNavigationList = jsonParam.toJavaList(CustomNavigationDto.class);
      //  return customNavigationService.customNavigationSort(customNavigationList);
        return ResultVo.ok(customNavigationList);
    }


    @RequestMapping(value = "/customNavigationSort2", method = RequestMethod.POST)
    public ResultVo customNavigationSort2(@RequestBody JSONObject jsonParam) {
        JSONArray array = jsonParam.getJSONArray("customNavigationList");
        List<CustomNavigationDto> customNavigationList = JSONObject.parseArray(array.toJSONString(), CustomNavigationDto.class);
        return ResultVo.ok(customNavigationList);
    }

    /*
   * 更新资源
   *  当路径变量名称和形参名一样时，@PathVatiable中的value可以不写
   * */
    @PutMapping("/student/{id}/{age}")
    public String mnodifyStudent(@PathVariable Integer id,@PathVariable Integer age){
        return "更新资源，执行put请求方式：id="+id+" aeg="+age;
    }

    /*删除资源
    * */
    @DeleteMapping("/student/{id}")
    public String removeStudent(@PathVariable Integer id){
        return "删除资源，执行delete请求方式：id="+id;
    }



    /** ----------------------其它处理 转发jsp路径及传递参数 ----*/
    //文件上传
    @RequestMapping("fileUpload")
    public String fileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) {
        if (file.isEmpty()) {
            redirectAttributes.addFlashAttribute("message", "请选择文件");
            return "redirect:请选择文件";
        }
        try {
            byte[] bytes = file.getBytes();
            Path path = Paths.get(Objects.requireNonNull(file.getOriginalFilename()));
            Files.write(path, bytes);
            redirectAttributes.addFlashAttribute("message", "成功上传 '"+file.getOriginalFilename() +"'");
            return "redirect:成功上传 '"+file.getOriginalFilename() +"'";
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "redirect:上传异常";
    }







//    @PostMapping  对象接收
//    public JsonResult addXXX(@RequestBody Ilog ilog)

    /*
     * @PostMapping("/dailyadd")
     * public JsonResult dailyAdd(@RequestBody Map<String,List<XXXEntity>> xxxEntityMap, HttpServletRequest request,
     *  HttpServletResponse response)  {
          List<XXXEntity>  xxxEntityList = (List<XXXEntity>) xxxEntityMap.get("xxxEntityList");//获取到list对象
       ...

    传对象List 方法1对应请求参数

    {
      "xxxEntityList":        [{
        "xxxx": "",
        "xxx": "1",
        "xxxx": "2022-05-10 20:56:28"
        "xxxDateList":["2022-08-17","2022-10-02","2022-10-03"],//参数属性为list
        "patrolmaintaintaskEndtime": "2022-05-11 16:40:28",
        "patrolmaintaintaskArea": "2",
        "patrolmaintaintaskDesc": "测试数据",
        "userids": "11000,11100" //参数属性为String，用逗号分割
        },
        {
        "xxxx": "",
        "xxxx": "1",
        "xxx": "2022-05-10 20:40:28",
        "xxx":"2022-06-30",
        "xxx":"16:30:00",
        "xxx":"17:00:00",
        "xxxDateList":["2022-08-17","2022-10-02","2022-10-03"],
        "userids": "11000,11100"
        }]
    }
     */


    /*
     *
     */

    @ResponseBody
    @RequestMapping(value = "/json/data", method = RequestMethod.POST,
            produces = "application/json;charset=UTF-8")
    public String getByJSON(@RequestBody JSONObject jsonParam) {
        // 直接将json信息打印出来
        System.out.println(jsonParam.toJSONString());

        // 将获取的json数据封装一层，然后在给返回
        JSONObject result = new JSONObject();
        result.put("msg", "ok");
        result.put("method", "json");
        result.put("data", jsonParam);

        return result.toJSONString();
    }

    @ResponseBody
    @RequestMapping(value = "/request/data", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    public String getByRequest(HttpServletRequest request) {

        //获取到JSONObject
        JSONObject jsonParam = this.getJSONParam(request);

        // 将获取的json数据封装一层，然后在给返回
        JSONObject result = new JSONObject();
        result.put("msg", "ok");
        result.put("method", "request");
        result.put("data", jsonParam);

        return result.toJSONString();
    }

    public JSONObject getJSONParam(HttpServletRequest request){
        JSONObject jsonParam = null;
        try {
            // 获取输入流
            BufferedReader streamReader = new BufferedReader(new InputStreamReader
                    (request.getInputStream(), "UTF-8"));

            // 写入数据到Stringbuilder
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = streamReader.readLine()) != null) {
                sb.append(line);
            }
            jsonParam = JSONObject.parseObject(sb.toString());
            // 直接将json信息打印出来
            System.out.println(jsonParam.toJSONString());
            streamReader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return jsonParam;
    }
}
